#pragma once
#include <istream>

using namespace std;

// Interface for classes implementing providers of values.
template<class TVal> class ISource {
    public:
        virtual ~ISource() {}
        virtual bool HasValues() = 0;
		virtual TVal Next() = 0;
};

class RandomSource : public ISource<float> {
	private:
		int _totalValues;
		int _generatedValues;
		float _magnitude;
	
	public:
		RandomSource(int totalValues, float magnitude);
		virtual bool HasValues();
		virtual float Next();	
};

// A class that implements a reader for the format defined in gen_data.py, from a binary or text input (depending on the stream type).
// Using an istream lets us abstract away the physical data source (file, socket, etc).
class VIReader : public ISource<float> {
	public:
		static const int RECORD_SIZE = 2;
		enum mode_t { Voltage, Current };
		VIReader(istream& in, mode_t mode);
		virtual bool HasValues();
		virtual float Next();

	private:
		istream& _in;
		mode_t _model;
		int _recordIndex;
		bool _initialised;
		unsigned int _blockTotal;
		unsigned int _blockCount;
		unsigned int _generatedValues;
		inline void TestNotEof();
		inline static unsigned long ReadLittleEndian32(istream& in);
		inline void ReadBlockSize();
		inline void ReadHeader();
};